#ifndef CONTAINER_H
#define CONTAINER_H

#include <cstdint>
#include <string>
#include <vector>
#include <exception>

#include "../persistencia/binarystream.h"
#include "../persistencia/serializable.h"

class ContainerFullException : std::exception {
};

template<class Record>
class Nullable {
    public:
        Nullable() : notNull(false) { }
        Record& get(){
            return record;
        }
        void set(Record record){
            this->record = record;
            notNull = true;
        }
        void unset(){
            notNull = false;
        }
        operator bool() const {
            return notNull;
        }
        operator Record() const {
            return record;
        }
    private:
        bool notNull;
        Record record;
};

template<class Key, class Record>
class Container : public Serializable
{
    public:
        Container();
        Container(u_int32_t blockSize);
        virtual ~Container();
        u_int32_t getSizeUsed() const;
        u_int32_t getCapacity() const;

        Nullable<Record> get(Key key);
        bool add(Record record, bool ignoreSize = false) throw (ContainerFullException);
        bool update(Record record) throw (ContainerFullException);
        bool remove(Key record);

        typename std::vector<Record>::iterator find(Key key, bool strict);
        std::vector<Record>& getRecords();
        std::vector<Record> empty();

        virtual void read(BinaryStream& in);
        virtual void write(BinaryStream& out);
        virtual std::string toString();

    protected:
        std::vector<Record> records;
        u_int32_t maxSize;
        u_int32_t size;
};


#endif // CONTAINER_H
